package ca.eloas.judging.model;

import com.googlecode.objectify.Ref;
import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Index;
import com.googlecode.objectify.annotation.Load;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * @author JP
 */
@Entity
public class JudgeObject extends DBObjectImpl<JudgeObject> implements Judge {

    @Index
    private String name;
    private String encryptedPassword;

    @Index  @Load
    List<Ref<CompetitionObject>> competitions = new ArrayList<Ref<CompetitionObject>>();
    private String salt;
    private boolean admin;

    protected JudgeObject() {
    }

    public JudgeObject(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void judgeCompetiton(CompetitionObject competition) {

        competitions.add(Ref.create(competition.getKey()));
    }

    public void setPassword(String clearTextPassword) {

            salt = UUID.randomUUID().toString();
            encryptedPassword = hashPassword(clearTextPassword, salt);
    }

    public static String hashPassword(String clearTextPassword, final String salt) {
        return Base64.encodeBase64URLSafeString(DigestUtils.sha512(clearTextPassword + salt));
    }

    public Iterable<CompetitionObject> getCompetitions() {

        ArrayList<CompetitionObject> comp = new ArrayList<CompetitionObject>();
        for (Ref<CompetitionObject> subordinate : competitions) {

            comp.add(subordinate.get());
        }

        return comp;
    }

    public boolean checkPassword(String clearTextPassword) {

        if (encryptedPassword == null) {

            throw new IllegalStateException("member " + name + " has null password");
        }
        return encryptedPassword.equals(hashPassword(clearTextPassword, salt));
    }

    public boolean isAdmin() {
        return admin;
    }

    public void setAdmin(boolean admin) {
        this.admin = admin;
    }
}
